package com.cuit.qx.utils;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.cuit.qx.service.AddWeatherStationService;
import com.cuit.qx.service.WarningService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;

import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}") //此注解相当于设置访问URL
public class WebSocket {

    private static final Logger LOG = LoggerFactory.getLogger(WebSocket.class);

    private Session session;

    public static CopyOnWriteArraySet<WebSocket> webSockets = new CopyOnWriteArraySet<>();

    private static Map<String, Session> sessionPool = new HashMap<String, Session>();

    private static int onLineNum = 0;//静态变量，记录当前在线连接数

    public static String warnLastTime;


    private WarningService getWarningService() {
        WarningService warningService = SpringContextUtils.getApplicationContext().getBean(WarningService.class);
        return warningService;
    }

    private AddWeatherStationService getAddWeatherService() {
        AddWeatherStationService addWeatherService = SpringContextUtils.getApplicationContext().getBean(AddWeatherStationService.class);
        return addWeatherService;
    }


    @OnOpen
    public void onOpen(Session session, @PathParam(value = "userId") String userId) {
        try {
            this.session = session;
            session.setMaxIdleTimeout(-1);
            webSockets.add(this);
            sessionPool.put(userId, session);
            LOG.info("【websocket消息】有新的连接，总数为:" + webSockets.size());
            sendAllMessage(null);
        } catch (Exception e) {
        }
    }

    @OnClose
    public void onClose() {
        try {
            webSockets.remove(this);
//            subOnlineNum();//在线数减1
            LOG.info("【websocket消息】连接断开，总数为:" + webSockets.size());
        } catch (Exception e) {
        }
    }

    @OnMessage
    public void onMessage(String message) {
        //todo 现在有个定时任务刷，应该去掉
        LOG.debug("【websocket message】get user info:" + message);
        JSONObject obj = new JSONObject();
        obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_CHECK);//业务类型
        obj.put(WebsocketConst.MSG_TXT, "心跳响应");//消息内容
        session.getAsyncRemote().sendText(obj.toJSONString());
    }

    // 此为广播消息,查询轮播图显示的内容,查询新增站点
    public synchronized void sendAllMessage(String message) {

        Map<String, Object> map2 = new HashMap<>();
        Map<String, Object> map3 = new HashMap<>();
        List<Map<String, Object>> arrayList = new ArrayList<>();
        map2.put("code", "warn");
        map2.put("data", getWarningService().getWarningListContent());

        if(getWarningService().getWarningLastTime().equals(warnLastTime)){
            map2.put("status","same");
        }else {
            map2.put("status","different");
        }

        map3.put("code", "station");
        map3.put("data", getAddWeatherService().getAllAddWeatherStation());
        arrayList.add(map2);
        arrayList.add(map3);

        for (WebSocket webSocket : webSockets) {
            try {
                if (webSocket.session.isOpen()) {
                    warnLastTime = getWarningService().getWarningLastTime();
                    webSocket.session.getAsyncRemote().sendText(JSONUtil.toJsonStr(arrayList));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    // 此为广播消息,查询新增站点
    public synchronized void sendAddWeatherMessage(String message) {
        for (WebSocket webSocket : webSockets) {
            try {
                if (webSocket.session.isOpen()) {
                    List<Map<String, Object>> arrayList = new ArrayList<>();
                    Map<String, Object> map = new HashMap<>();
                    Map<String, Object> map1 = new HashMap<>();
                    map.put("code", "station");
                    map.put("data", getAddWeatherService().getAllAddWeatherStation());
                    map1.put("code", "warn");
                    map1.put("data", new ArrayList<>());
                    arrayList.add(map);
                    arrayList.add(map1);
                    webSocket.session.getAsyncRemote().sendText(JSONUtil.toJsonStr(arrayList));
//                    LOG.info("【websocket message】addStationContent sure:" + JSONUtil.toJsonStr(arrayList));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 此为单点消息
    public void sendOneMessage(String userId, String message) {
        Session session = sessionPool.get(userId);
        if (session != null && session.isOpen()) {
            try {
                LOG.info("【websocket消息】 单点消息:" + message);
                session.getAsyncRemote().sendObject(getWarningService().getWarnings());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 此为单点消息(多人)
    public synchronized void sendMoreMessage(String[] userIds, String message) {
        for (String userId : userIds) {
            Session session = sessionPool.get(userId);
            if (session != null && session.isOpen()) {
                try {
                    LOG.info("【websocket消息】 单点消息:" + message);
                    session.getAsyncRemote().sendObject(getWarningService().getWarnings());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * @param
     * @return int
     * @author wyh
     * @description 获取当前在线数, 使用关键字
     **/
    public synchronized int getOnlineNum() {
        return onLineNum;
    }


    /**
     * @param
     * @return void
     * @author wyh
     * @description 在线数加1，注意关键字
     **/
    public static synchronized void addOnlineNum() {
        onLineNum++;
    }


    /**
     * @param
     * @return void
     * @author wyh
     * @description 在线数减1
     **/
    public static synchronized void subOnlineNum() {
        if (onLineNum > 0) {
            onLineNum--;
        }
    }

}
